// 单元测试 - 工具函数和数据结构
//
// 本文件包含不需要网络连接的单元测试

use akoption::types::*;
use akoption::utils::parse::*;

// ============ 数据结构测试 ============

/// 测试：EndMonth 结构体
/// 
/// 验证点：
/// 1. 能够正确创建 EndMonth
/// 2. 支持 YYMM 和 YYYYMM 两种格式
#[test]
fn test_end_month_creation() {
    // 测试 YYMM 格式
    let month1 = EndMonth::new("2511");
    assert_eq!(month1.0, "2511");
    
    // 测试 YYYYMM 格式
    let month2 = EndMonth::new("202511");
    assert_eq!(month2.0, "202511");
    
    println!("✓ EndMonth 创建测试通过");
}

/// 测试：FinanceSymbol 枚举
/// 
/// 验证点：
/// 1. 所有枚举值都能正确创建
#[test]
fn test_finance_symbol_enum() {
    let symbols = vec![
        FinanceSymbol::Sse50Etf,
        FinanceSymbol::Sse300Etf,
        FinanceSymbol::Sse500Etf,
        FinanceSymbol::SseKc50Etf,
        FinanceSymbol::SseKc50EtfYfd,
        FinanceSymbol::Szse300Etf,
    ];
    
    assert_eq!(symbols.len(), 6);
    println!("✓ FinanceSymbol 枚举测试通过");
}

/// 测试：SseUnderlying 枚举
/// 
/// 验证点：
/// 1. 所有标的物枚举值都能正确创建
#[test]
fn test_sse_underlying_enum() {
    let underlyings = vec![
        SseUnderlying::HuaXia50,
        SseUnderlying::HuaTai300,
        SseUnderlying::NanFang500,
        SseUnderlying::KeChuang50,
        SseUnderlying::KeChuang50Yfd,
    ];
    
    assert_eq!(underlyings.len(), 5);
    println!("✓ SseUnderlying 枚举测试通过");
}

/// 测试：CffexIndex 枚举
/// 
/// 验证点：
/// 1. 中金所三大指数枚举值都能正确创建
#[test]
fn test_cffex_index_enum() {
    let indices = vec![
        CffexIndex::IO,
        CffexIndex::MO,
        CffexIndex::HO,
    ];
    
    assert_eq!(indices.len(), 3);
    println!("✓ CffexIndex 枚举测试通过");
}

// ============ 工具函数测试 ============

/// 测试：parse_f64 函数
/// 
/// 验证点：
/// 1. 能够正确解析普通数字字符串
/// 2. 能够处理带逗号的数字
/// 3. 能够处理空字符串
/// 4. 能够处理无效字符串
#[test]
fn test_parse_f64() {
    // 测试普通数字
    assert_eq!(parse_f64("123.45"), Some(123.45));
    assert_eq!(parse_f64("0.01"), Some(0.01));
    
    // 测试带逗号的数字
    assert_eq!(parse_f64("1,234.56"), Some(1234.56));
    assert_eq!(parse_f64("1,234,567.89"), Some(1234567.89));
    
    // 测试空字符串
    assert_eq!(parse_f64(""), None);
    assert_eq!(parse_f64("   "), None);
    
    // 测试无效字符串
    assert_eq!(parse_f64("abc"), None);
    assert_eq!(parse_f64("--"), None);
    
    // 测试负数
    assert_eq!(parse_f64("-123.45"), Some(-123.45));
    
    println!("✓ parse_f64 函数测试通过");
}

/// 测试：parse_i64 函数
/// 
/// 验证点：
/// 1. 能够正确解析整数字符串
/// 2. 能够处理带逗号的整数
/// 3. 能够处理空字符串
/// 4. 能够处理无效字符串
#[test]
fn test_parse_i64() {
    // 测试普通整数
    assert_eq!(parse_i64("123"), Some(123));
    assert_eq!(parse_i64("0"), Some(0));
    
    // 测试带逗号的整数
    assert_eq!(parse_i64("1,234"), Some(1234));
    assert_eq!(parse_i64("1,234,567"), Some(1234567));
    
    // 测试空字符串
    assert_eq!(parse_i64(""), None);
    assert_eq!(parse_i64("   "), None);
    
    // 测试无效字符串
    assert_eq!(parse_i64("abc"), None);
    assert_eq!(parse_i64("12.34"), None); // 小数应该失败
    
    // 测试负数
    assert_eq!(parse_i64("-123"), Some(-123));
    
    println!("✓ parse_i64 函数测试通过");
}

// ============ 序列化测试 ============

/// 测试：EmOptionTick 序列化
/// 
/// 验证点：
/// 1. 能够正确序列化为 JSON
/// 2. JSON 字段名称为中文
#[test]
fn test_em_option_tick_serialization() {
    let tick = EmOptionTick {
        code: "10010201".to_string(),
        name: "科创板50购11月1783A".to_string(),
        last: Some(0.0102),
        change: Some(0.0022),
        change_pct: Some(27.5),
        volume: Some(1234.0),
        amount: Some(12580.0),
        open_interest: Some(5678.0),
        strike: Some(1.783),
        days_remaining: Some(28),
    };
    
    let json = serde_json::to_string(&tick).unwrap();
    
    // 验证 JSON 包含中文字段名
    assert!(json.contains("代码"));
    assert!(json.contains("名称"));
    assert!(json.contains("最新价"));
    
    println!("✓ EmOptionTick 序列化测试通过");
    println!("  JSON: {}", json);
}

/// 测试：OptionValueAnalysis 序列化
/// 
/// 验证点：
/// 1. 能够正确序列化为 JSON
/// 2. JSON 字段名称为中文
#[test]
fn test_option_value_analysis_serialization() {
    let analysis = OptionValueAnalysis {
        code: "10010201".to_string(),
        name: "科创板50购11月1783A".to_string(),
        last: Some(0.0102),
        change_pct: Some(27.5),
        intrinsic_value: Some(0.0),
        time_value: Some(0.0102),
        leverage: Some(150.0),
        actual_leverage: Some(120.0),
        underlying_last: Some(1.517),
        underlying_volatility: Some(31.41),
        expire_date: "2025-11-26".to_string(),
    };
    
    let json = serde_json::to_string(&analysis).unwrap();
    
    // 验证 JSON 包含中文字段名
    assert!(json.contains("期权代码"));
    assert!(json.contains("内在价值"));
    assert!(json.contains("时间价值"));
    
    println!("✓ OptionValueAnalysis 序列化测试通过");
}

/// 测试：OptionRiskAnalysis 序列化
/// 
/// 验证点：
/// 1. 能够正确序列化为 JSON
/// 2. Greeks 字段正确
#[test]
fn test_option_risk_analysis_serialization() {
    let analysis = OptionRiskAnalysis {
        code: "10010201".to_string(),
        name: "科创板50购11月1783A".to_string(),
        last: Some(0.0102),
        change_pct: Some(27.5),
        delta: Some(0.25),
        gamma: Some(0.05),
        vega: Some(0.0384),
        theta: Some(-0.0740),
        rho: Some(0.0050),
        implied_volatility: Some(45.2),
        expire_date: "2025-11-26".to_string(),
    };
    
    let json = serde_json::to_string(&analysis).unwrap();
    
    // 验证 JSON 包含 Greeks 字段
    assert!(json.contains("Delta"));
    assert!(json.contains("Gamma"));
    assert!(json.contains("Vega"));
    assert!(json.contains("Theta"));
    assert!(json.contains("Rho"));
    
    println!("✓ OptionRiskAnalysis 序列化测试通过");
}

// ============ 反序列化测试 ============

/// 测试：从 JSON 反序列化 EmOptionTick
/// 
/// 验证点：
/// 1. 能够正确从 JSON 反序列化
/// 2. 字段值正确
#[test]
fn test_em_option_tick_deserialization() {
    let json = r#"{
        "代码": "10010201",
        "名称": "科创板50购11月1783A",
        "最新价": 0.0102,
        "涨跌额": 0.0022,
        "涨跌幅": 27.5,
        "成交量": 1234.0,
        "成交额": 12580.0,
        "持仓量": 5678.0,
        "行权价": 1.783,
        "剩余天数": 28
    }"#;
    
    let tick: EmOptionTick = serde_json::from_str(json).unwrap();
    
    assert_eq!(tick.code, "10010201");
    assert_eq!(tick.name, "科创板50购11月1783A");
    assert_eq!(tick.last, Some(0.0102));
    assert_eq!(tick.days_remaining, Some(28));
    
    println!("✓ EmOptionTick 反序列化测试通过");
}

// ============ 边界条件测试 ============

/// 测试：处理 None 值
/// 
/// 验证点：
/// 1. Option 字段能够正确处理 None
/// 2. 序列化时 None 值正确表示
#[test]
fn test_option_fields_with_none() {
    let tick = EmOptionTick {
        code: "TEST001".to_string(),
        name: "测试期权".to_string(),
        last: None,  // 无最新价
        change: None,
        change_pct: None,
        volume: None,
        amount: None,
        open_interest: None,
        strike: Some(100.0),
        days_remaining: Some(30),
    };
    
    let json = serde_json::to_string(&tick).unwrap();
    assert!(json.contains("null"));
    
    // 反序列化应该也能正常工作
    let deserialized: EmOptionTick = serde_json::from_str(&json).unwrap();
    assert_eq!(deserialized.last, None);
    assert_eq!(deserialized.strike, Some(100.0));
    
    println!("✓ Option 字段 None 值测试通过");
}

/// 测试：空字符串处理
/// 
/// 验证点：
/// 1. 空字符串能够正确处理
#[test]
fn test_empty_string_handling() {
    let tick = EmOptionTick {
        code: "".to_string(),  // 空代码
        name: "".to_string(),  // 空名称
        last: None,
        change: None,
        change_pct: None,
        volume: None,
        amount: None,
        open_interest: None,
        strike: None,
        days_remaining: None,
    };
    
    let json = serde_json::to_string(&tick).unwrap();
    let deserialized: EmOptionTick = serde_json::from_str(&json).unwrap();
    
    assert_eq!(deserialized.code, "");
    assert_eq!(deserialized.name, "");
    
    println!("✓ 空字符串处理测试通过");
}

// ============ 性能测试 ============

/// 测试：大量数据序列化性能
/// 
/// 验证点：
/// 1. 能够快速序列化大量数据
#[test]
fn test_bulk_serialization_performance() {
    use std::time::Instant;
    
    // 创建 1000 条模拟数据
    let mut data = Vec::new();
    for i in 0..1000 {
        data.push(EmOptionTick {
            code: format!("CODE{:06}", i),
            name: format!("期权{}", i),
            last: Some(100.0 + i as f64),
            change: Some(1.0),
            change_pct: Some(1.5),
            volume: Some(1000.0),
            amount: Some(100000.0),
            open_interest: Some(5000.0),
            strike: Some(100.0),
            days_remaining: Some(30),
        });
    }
    
    let start = Instant::now();
    let json = serde_json::to_string(&data).unwrap();
    let duration = start.elapsed();
    
    println!("✓ 序列化 1000 条数据耗时: {:?}", duration);
    println!("  JSON 大小: {} bytes", json.len());
    
    // 性能应该在合理范围内（< 100ms）
    assert!(duration.as_millis() < 100, "序列化性能不佳");
}

// ============ 测试运行器 ============

/// 运行所有单元测试
/// 
/// 使用方法：
/// ```bash
/// cargo test --test unit_tests -- --nocapture
/// ```
#[test]
fn run_all_unit_tests() {
    println!("\n========================================");
    println!("  AkShare 期权单元测试");
    println!("========================================\n");
    
    println!("所有单元测试已通过！");
    println!("\n运行集成测试请使用：");
    println!("cargo test --test integration_tests -- --ignored --nocapture");
}
